package com.liholin.springboot.sample.utils;

import com.aliyun.openservices.log.Client;
import com.aliyun.openservices.log.common.LogContent;
import com.aliyun.openservices.log.common.LogItem;
import com.aliyun.openservices.log.exception.LogException;
import com.aliyun.openservices.log.request.PutLogsRequest;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.model.*;
import org.springframework.web.multipart.MultipartFile;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.util.*;

public class AliyunOperation {
    /**
     * 写入日志
     *
     * @param endpoint        project 所属区域匹配
     * @param accessKeyId     阿里云访问密钥ID
     * @param accessKeySecret 阿里云访问密钥
     * @param project         项目名称
     * @param logstore        日志库名称
     */
    public static void uploadJournal(String endpoint, String accessKeyId, String accessKeySecret, String project,
                                     String logstore, ArrayList<LogContent> contents) {
        Client client = new Client(endpoint, accessKeyId, accessKeySecret);
        Vector<LogItem> logGroup = new Vector<LogItem>();
        LogItem logItem = new LogItem((int) (new Date().getTime() / 1000));
        logItem.SetLogContents(contents);
        logGroup.add(logItem);
        PutLogsRequest req2 = new PutLogsRequest(project, logstore, "", "", logGroup);
        try {
            client.PutLogs(req2);
        } catch (LogException e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传文件
     *
     * @param endpoint        project 所属区域匹配
     * @param accessKeyId     阿里云访问密钥ID
     * @param accessKeySecret 阿里云访问密钥
     * @param bucketName      文件夹
     * @param fileName        文件名
     * @param path            上传文件路径
     */
    public static void uploadFile(String endpoint, String accessKeyId, String accessKeySecret, String bucketName,
                                  String fileName, String path) {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        PutObjectResult result = ossClient.putObject(bucketName, fileName, new File(path));
        ossClient.shutdown();
    }

    /**
     * 大文件上传初始化
     * @param endpoint
     * @param accessKeyId
     * @param accessKeySecret
     * @param bucketName
     * @param fileName
     * @return
     */
    public static String initiateMultipartUpload(String endpoint, String accessKeyId, String accessKeySecret, String bucketName,
                                                 String fileName){
        // 创建OSSClient实例
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        // 初始化一个分片上传事件
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, fileName);
        InitiateMultipartUploadResult result = ossClient.initiateMultipartUpload(request);
        ossClient.shutdown();
        return result.getUploadId();
    }

    /**
     * 大文件分片上传
     * @param endpoint
     * @param accessKeyId
     * @param accessKeySecret
     * @param uploadId
     * @param bucketName
     * @param fileName
     * @param path
     * @param partNo
     * @return
     */
    public static PartETag uploadPart(String endpoint, String accessKeyId, String accessKeySecret,
                                               String uploadId, String bucketName, String fileName, String path, int partNo){
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        final File sampleFile = new File(path);
        InputStream inputStream = null;
        try {
            inputStream = new FileInputStream(sampleFile);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        }
        //inputStream.skip(startPos);
        UploadPartRequest uploadPartRequest = new UploadPartRequest();
        uploadPartRequest.setBucketName(bucketName);
        uploadPartRequest.setKey(fileName);
        uploadPartRequest.setUploadId(uploadId);
        uploadPartRequest.setInputStream(inputStream);
        //uploadPartRequest.setPartSize();
        uploadPartRequest.setPartNumber(partNo);
        UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
        ossClient.shutdown();
        return uploadPartResult.getPartETag();
    }

    /**
     * 完成分片上传
     * @param partETags
     * @param endpoint
     * @param accessKeyId
     * @param accessKeySecret
     * @param uploadId
     * @param bucketName
     * @param fileName
     */
    public static void completeMultipartUpload(List<PartETag> partETags,String endpoint, String accessKeyId, String accessKeySecret,
                                               String uploadId, String bucketName, String fileName){
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        // 完成分片上传
        Collections.sort(partETags, new Comparator<PartETag>() {
            @Override
            public int compare(PartETag o1, PartETag o2) {
                return o1.getPartNumber() - o2.getPartNumber();
            }
        });
        CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, fileName, uploadId, partETags);
        ossClient.completeMultipartUpload(completeMultipartUploadRequest);
        ossClient.shutdown();
    }
    /**
     * 断点续传文件
     *
     * @param endpoint        project 所属区域匹配
     * @param accessKeyId     阿里云访问密钥ID
     * @param accessKeySecret 阿里云访问密钥
     * @param bucketName      文件夹
     * @param fileName        文件名
     * @param path            上传文件路径
     */
    public static void multipartUploadFile(String endpoint, String accessKeyId, String accessKeySecret, String bucketName,
                                           String fileName, String path) {
        // 创建OSSClient实例
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        // 初始化一个分片上传事件
        InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, fileName);
        InitiateMultipartUploadResult result = ossClient.initiateMultipartUpload(request);
        String uploadId = result.getUploadId();
        // 上传分片
        List<PartETag> partETags = new ArrayList<PartETag>();
        final long partSize = 1 * 1024 * 1024L;
        final File sampleFile = new File(path);
        long fileLength = sampleFile.length();
        int partCount = (int) (fileLength / partSize);
        if (fileLength % partSize == 0){
            partCount ++;
        }
        try {
            for (int i = 0; i < partCount; i++) {
                long startPos = i * partSize;
                long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
                InputStream inputStream = new FileInputStream(sampleFile);
                inputStream.skip(startPos);
                UploadPartRequest uploadPartRequest = new UploadPartRequest();
                uploadPartRequest.setBucketName(bucketName);
                uploadPartRequest.setKey(fileName);
                uploadPartRequest.setUploadId(uploadId);
                uploadPartRequest.setInputStream(inputStream);
                uploadPartRequest.setPartSize(curPartSize);
                uploadPartRequest.setPartNumber(i + 1);
                UploadPartResult uploadPartResult = ossClient.uploadPart(uploadPartRequest);
                partETags.add(uploadPartResult.getPartETag());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
        // 完成分片上传
        Collections.sort(partETags, new Comparator<PartETag>() {
            @Override
            public int compare(PartETag o1, PartETag o2) {
                return o1.getPartNumber() - o2.getPartNumber();
            }
        });
        CompleteMultipartUploadRequest completeMultipartUploadRequest = new CompleteMultipartUploadRequest(bucketName, fileName, uploadId, partETags);
        ossClient.completeMultipartUpload(completeMultipartUploadRequest);
        ossClient.shutdown();
        /*ObjectMetadata meta = new ObjectMetadata();
        meta.setContentType("text/plain");
        UploadFileRequest uploadFileRequest = new UploadFileRequest(bucketName, fileName);
        // 指定上传的本地文件
        uploadFileRequest.setUploadFile(path);
        // 指定上传并发线程数
        uploadFileRequest.setTaskNum(5);
        // 指定上传的分片大小
        uploadFileRequest.setPartSize(1 * 1024 * 1024);
        // 开启断点续传
        uploadFileRequest.setEnableCheckpoint(true);
        uploadFileRequest.setObjectMetadata(meta);
        // 断点续传上传
        try {
            ossClient.uploadFile(uploadFileRequest);
        } catch (Throwable throwable) {
            throwable.printStackTrace();
        }
        ossClient.shutdown();*/
    }

    /**
     * 文件是否存在
     *
     * @param endpoint        project 所属区域匹配
     * @param accessKeyId     阿里云访问密钥ID
     * @param accessKeySecret 阿里云访问密钥
     * @param bucketName      文件夹
     * @param fileName        文件名 开头不带"/"
     */
    public static boolean fileExist(String endpoint, String accessKeyId, String accessKeySecret, String bucketName,
                                    String fileName) {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        boolean flg = ossClient.doesObjectExist(bucketName, fileName);
        ossClient.shutdown();
        return flg;
    }

    /**
     * 上传文件流
     *
     * @param endpoint        project 所属区域匹配
     * @param accessKeyId     阿里云访问密钥ID
     * @param accessKeySecret 阿里云访问密钥
     * @param bucketName      文件夹
     * @param fileName        文件名
     */
    public static void uploadFile(InputStream multipartFile, String endpoint, String accessKeyId, String accessKeySecret, String bucketName,
                                  String fileName) {
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        ossClient.putObject(bucketName, fileName, multipartFile);
        ossClient.shutdown();
    }

    /**
     * 上传Base64
     *
     * @param endpoint        project 所属区域匹配
     * @param accessKeyId     阿里云访问密钥ID
     * @param accessKeySecret 阿里云访问密钥
     * @param bucketName      文件夹
     * @param fileName        文件名
     */
    public static void uploadFileBase64(String multipartFile, String endpoint, String accessKeyId, String accessKeySecret, String bucketName,
                                        String fileName) throws Exception {
       /* BASE64Decoder base64Decoder = new BASE64Decoder();
        byte[] bytes = base64Decoder.decodeBuffer(multipartFile);
        InputStream inputStream = new ByteArrayInputStream(bytes);*/
        String imagePath = "/user/mindy/Desktop/" + fileName;
        FileToBinary.generateFile("data:image/png;base64," + multipartFile, imagePath);
        File file = new File(imagePath);
//        SerialBlob serialBlob = decodeToImage(multipartFile);
//        InputStream binaryStream = serialBlob.getBinaryStream();
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        ObjectMetadata meta = new ObjectMetadata();
        meta.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        meta.setContentLength(file.length());
        ossClient.putObject(bucketName, fileName, file, meta);
        ossClient.shutdown();
    }
    /*public static void uploadFile(String endpoint, String accessKeyId, String accessKeySecret, String storageName, String file, String name) {
        // 创建OSSClient实例
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        // 上传文件
        ossClient.putObject(storageName, file, new File(name));
        // 关闭client
        ossClient.shutdown();
    }*/

    /**
     * 上传文件MultipartFile
     * @param endpoint project 所属区域匹配
     * @param accessKeyId  阿里云访问密钥ID
     * @param accessKeySecret 阿里云访问密钥
     * @param bucketName 文件夹
     * @param fileName 文件名
     */
    public static String uploadFile(MultipartFile multipartFile, String endpoint, String accessKeyId, String accessKeySecret, String bucketName,
                                    String fileName){
        OSSClient ossClient = new OSSClient(endpoint, accessKeyId, accessKeySecret);
        try {
            ossClient.putObject(bucketName, fileName, multipartFile.getInputStream());
        } catch (IOException e) {
            e.printStackTrace();
        }
        ossClient.shutdown();
        return endpoint+bucketName+fileName;
    }

    /**
     * 签名
     * @param data 需要签名的数据
     * @param key 密钥
     * @return
     * @throws NoSuchAlgorithmException
     * @throws InvalidKeyException
     */
    public static String signature(String data, String key) throws NoSuchAlgorithmException, InvalidKeyException {
        SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
        Mac mac = Mac.getInstance("HmacSHA1");
        mac.init(signingKey);
        byte[] rawHmac = mac.doFinal(data.getBytes());
        return com.sun.org.apache.xerces.internal.impl.dv.util.Base64.encode(rawHmac);//Base64.encodeBase64String(rawHmac);
    }
    public static String getTimeStamp(){
        SimpleDateFormat format = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
        Calendar instance = Calendar.getInstance(TimeZone.getTimeZone("GMT+0"));
        format.setCalendar(instance);
        return format.format(new Date());
    }
}
